package server;

import java.net.InetAddress;
import java.rmi.*;
import java.rmi.server.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

import model.*;
import model.exceptions.*;

import common.*;

public class ServerController extends UnicastRemoteObject implements
		ServerInterface {
	private ArrayList<User> clients;
	private ArrayList<Conversation> conversations;
	private ServerFrame frame;

	public ServerController() throws RemoteException {
		super();
		clients = new ArrayList<User>();
		conversations = new ArrayList<Conversation>();
	}

	public void begin(ServerFrame frame) throws Exception {
		this.frame = frame;

		frame.println("Server listening on "
				+ InetAddress.getLocalHost().getHostAddress());
	}

	@Override
	public synchronized ArrayList<String> getAllUsers() throws RemoteException {
		ArrayList<String> list = new ArrayList<String>();

		Iterator<User> it = clients.iterator();
		while (it.hasNext())
			list.add(it.next().getName());

		return list;
	}

	protected void userLoggedin(String name) {
		Iterator<User> it = clients.iterator();
		while (it.hasNext())
			try {
				User user=it.next();
				if(!user.getName().equals(name))
					user.getInterface().userLoggedin(name);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
	}

	protected void userLoggedout(String name) {
		Iterator<User> it = clients.iterator();
		while (it.hasNext())
			try {
				ClientInterface client=it.next().getInterface();
				if(client!=null)
					client.userLoggedout(name);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
	}

	@Override
	public synchronized void login(String name, String password, ClientInterface clientController) throws RemoteException, AbstractException {
		User user = findUser(name);
		if (user == null)
			throw new WrongUsernameException();
		user.login(password, clientController);
		userLoggedin(name);
	}

	private User findUser(String name) {
		Iterator<User> it = clients.iterator();
		while (it.hasNext()) {
			User user = it.next();
			if (user.getName().equals(name))
				return user;
		}
		return null;
	}

	@Override
	public synchronized void registerUser(String name, String password,
			ClientInterface clientController) throws RemoteException,
			AbstractException {
		if (findUser(name) != null)
			throw new UserAlreadyExistsException();
		clients.add(new User(name, password, clientController));
		userLoggedin(name);
	}

	@Override
	public synchronized void logout(String name) throws RemoteException {
		findUser(name).logout();
		userLoggedout(name);
	}

	@Override
	public synchronized void sendMessage(Message message)
			throws RemoteException {
		Iterator<Conversation> it = conversations.iterator();
		while (it.hasNext()) {
			Conversation conversation = it.next();
			if (conversation.containsUser(findUser(message.getUser())))
				conversation.sendMessage(message);
		}
	}

	protected void sendMessageTo(Message message, User user) {
		try {
			user.getInterface().takeMessage(message);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void startConversation(String opponentName, String name)
			throws RemoteException, AbstractException {
		User opponent = findUser(opponentName);
		opponent.getInterface().startConversation();

		conversations.add(new Conversation(opponent, findUser(name), this));
	}

	@Override
	public void sendChat(Message message) throws RemoteException {
		Iterator<User> it=clients.iterator();
		while(it.hasNext())
			try {
				ClientInterface client=it.next().getInterface();
				if(client!=null)
					client.takeChat(message);
			} catch(RemoteException e) {
				e.printStackTrace();
			}
	}
}